using System;

namespace SymbolicDiff
{
	class MainClass
	{
			
		//Função para identificar se a string é numérica
        public static bool IsNumericString(string text)
        {
            foreach (char c in text)
            {
                if (!Char.IsNumber(c))
                {
                    return false;
                }
            }
            return true;
        }

        // Função para contar quantidade de certa string contida numa string
        public static int CountStringOccurrences(string text, string pattern)
        {
            // Loop through all instances of the string 'text'.
            int count = 0;
            int i = 0;
            while ((i = text.IndexOf(pattern, i)) != -1)
            {
                i += pattern.Length;
                count++;
            }
            return count;
        }

        // Função privada para o comando de derivada
        public static string[] getcharpot(string s)
        {
            string[] num = new string[] { "", "" };
            int n = s.Length;
            for (int i = 0; i < n; i++)
            {
                if (Char.IsNumber(Convert.ToChar(s.Substring(i, 1))))
                {
                    num[0] += s.Substring(i, 1);
                }
                else
                {
                    num[1] += s.Substring(i, 1);
                }
            }

            return num;
        }

        public static string der(string s)
        {
            if (CountStringOccurrences(s, "x") > 0)
            {
                if (CountStringOccurrences(s, "^") > 0)
                {
					string PreSplit;
					string PosSplit;
                    char[] delimiters = new char[] { 'x', '^' };
                    string[] e = s.Split(delimiters, StringSplitOptions.RemoveEmptyEntries);
					
					// Correção do Split
					// Pra funções como "x^2" o Split quebrava a string em apenas um elemento do array.
					if(e.Length == 1){
						PreSplit = "1";
						PosSplit = e[0];
					}
					else
					{
						PreSplit = e[0];
						PosSplit = e[1];
					}
					
                    if (PosSplit == "0")
                        return "";
                    if (PreSplit == "")
                        PreSplit = "1";
                    if (PreSplit == "-")
                        PreSplit = "-1";

                    string[] bas, exp;
                    bas = getcharpot(PreSplit);
                    exp = getcharpot(PosSplit);

                    if (exp[0] == "")
                        exp[0] = "1";


                    string opfrac;
                    string multfrac = Convert.ToString(Convert.ToInt16(bas[0]) * Convert.ToInt16(exp[0])) + bas[1] + exp[1];
                    if (IsNumericString(PosSplit))
                    {
                        opfrac = Convert.ToString(Convert.ToInt16(PosSplit) - 1);
                    }
                    else
                    {
                        opfrac = "(" + PosSplit + "-1)";
                    }

                    if (opfrac == "1")
                    {
                        return multfrac + "x";
                    }
                    if (opfrac == "0")
                    {
                        return multfrac;
                    }
                    else
                    {
                        return multfrac + "x^" + opfrac;
                    }
                }
                else
                {
                    string[] a = s.Split("x".ToCharArray());
                    if (a[0] == "" || a[0] == "-")
                    {
                        return s.Replace("x", "1");
                    }
                    else
                    {
                        return s.Replace("x", "");
                    }
                }
            }
            else
            {
                return "";
            }
        }

        public static string derivative(string s)
        {
            string derivative_var = "";
            s = s.Replace("-", "+-");
            if (CountStringOccurrences(s, "+") > 0)
            {
                string[] e = s.Split("+".ToCharArray());
                int count = e.Length;
                bool is_der = false;
                for(int i=0; i<count; i++)
                {
                    string d = der(e[i]);
                    if(is_der == true && d != "")
                    {
                        derivative_var += "+";
                    }
                    if(d != "")
                    {
                        derivative_var += d;
                        is_der = true;
                    }
                }
            }
            else
            {
                string d = der(s);
                if(d != "")
                {
                    derivative_var += d;
                }
            }

            if (derivative_var != "")
            {
                return derivative_var;
            }
            else
            {
                return "0";
            }
        }
		
		//simplificar equação com a substituição
		public static string[] Simplify (string s)
		{
			string[] L = new string[1];
			string[] b = new string[2];
			string Actuallyk;
			s = s.Replace(" ", "");
			//Console.WriteLine("1");
			if (CountStringOccurrences(s, "(") == CountStringOccurrences(s, ")"))
			{
				int m = 0;
				//Console.WriteLine("2");
				while (CountStringOccurrences(s, "(") > 0)
				{
					string[] e = s.Split("(".ToCharArray());
					int n = e.Length;
					//Console.WriteLine("e[n-1] = "+e[n-1]);
					string[] k= e[n-1].Split(")".ToCharArray());
					
					//Console.WriteLine("3");
					if (CountStringOccurrences(k[0], "*") + CountStringOccurrences(k[0], "/") > 1)
					{
						while (CountStringOccurrences(k[0], "*") + CountStringOccurrences(k[0], "/") > 1)
						{
							string[] u = k[0].Split("*".ToCharArray());
							if (CountStringOccurrences(u[0], "/") == 0 && CountStringOccurrences(u[1], "/") == 0)
							{
								b[0] = u[0].Replace("-", "+-");
								b[1] = u[1].Replace("-", "+-");
								string[] x = b[0].Split("+".ToCharArray());
								string[] y = b[1].Split("+".ToCharArray());
								L[m] = x[x.Length-1]+ "*" +y[0];
							}
							else if (CountStringOccurrences(u[0], "/") > 0)
							{
								string[] a = u[0].Split("/".ToCharArray());
								a[0] = a[0].Replace("-", "+-");
								a[1] = a[1].Replace("-", "+-");
								string[] x = a[0].Split("+".ToCharArray());
								string[] y = a[1].Split("+".ToCharArray());
								L[m] = x[x.Length-1]+ "/" +y[0];
							}
							else if (CountStringOccurrences(k[1], "/") > 0)
							{
								string[] z = u[1].Split("/".ToCharArray());
								z[0] = z[0].Replace("-", "+-");
								z[1] = u[0].Replace("-", "+-");
								string[] x = z[1].Split("+".ToCharArray());
								string[] y = z[0].Split("+".ToCharArray());
								L[m] = x[x.Length-1]+ "*" +y[0];
							}
							k[0] = k[0].Replace(L[m], "@L"+ m +"@");
							s = s.Replace(L[m], "@L"+ m +"@");
							m++;
						}
					}
					else
					{
						//Console.WriteLine("k[0] = "+k[0]);
						L[m] = k[0];
						s = s.Replace("("+ L[m] +")", "@L"+ m +"@");
						m++;
						Array.Resize(ref L, L.Length + 1);
					}
					
					// Tentativa de correção em relação ao k[0]
					Actuallyk = k[0];
				}
				if (CountStringOccurrences(s, "*") + CountStringOccurrences(s, "/") > 1)
				{
					while (CountStringOccurrences(s, "*") + CountStringOccurrences(s, "/") > 1)
					{
						string[] u = s.Split("*".ToCharArray());
						if (CountStringOccurrences(u[0], "/") == 0 && CountStringOccurrences(u[1], "/") == 0)
						{
							b[0] = u[0].Replace("-", "+-");
							b[1] = u[1].Replace("-", "+-");
							string[] x = b[0].Split("+".ToCharArray());
							string[] y = b[1].Split("+".ToCharArray());
							L[m] = x[x.Length-1]+ "*" +y[0];
						}
						else if (CountStringOccurrences(u[0], "/") > 0)
						{
							string[] a = u[0].Split("/".ToCharArray());
							a[0] = a[0].Replace("-", "+-");
							a[1] = a[1].Replace("-", "+-");
							string[] x = a[0].Split("+".ToCharArray());
							string[] y = a[1].Split("+".ToCharArray());
							L[m] = x[x.Length-1]+ "/" +y[0];
						}
						else if (CountStringOccurrences(u[1], "/") > 0)
						{
							string[] z = u[1].Split("/".ToCharArray());
							z[0] = z[0].Replace("-", "+-");
							z[1] = u[0].Replace("-", "+-");
							string[] x = z[1].Split("+".ToCharArray());
							string[] y = z[0].Split("+".ToCharArray());
							L[m] = x[x.Length-1]+ "*" +y[0];
						}
						Actuallyk = Actuallyk.Replace(L[m], "@L"+ m +"@");
						s = s.Replace(L[m], "@L"+ m +"@");
						m++;
					}
				}
				L[m] = s;
				return L;
			}
			else
			{
				Console.WriteLine("Erro na entrada: há parêntesis definidos incorretamente.");
				return L;
			}
		} 
		
		public static void Main (string[] args)
		{
			//string[] oi = new string[1];
			//oi[0] = "oi"; //Simplify("oi");
			//string ab = oi[0].Replace("oi", "ub");
			//oi[0].Replace("oi", "12");
			//Console.WriteLine(oi[0]+ "haha" + oi[0].Replace("oi","ua") +"hehe"+ab);
			while(true)
			{
				string s = Console.ReadLine();
				if(s == "limpar")
					Console.Clear();
				else
				{
					//Console.WriteLine(derivative(s));
					string[] Teste = Simplify(s);
					for(int i=0; i<Teste.Length; i++)
					{
						Console.WriteLine(i+" = "+Teste[i]);
					}
				}
			}
		}

	}
}
